package com.eddie.juc.cf;

import lombok.*;
import lombok.experimental.Accessors;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

/**
 * @author Eddie
 * @date 2022/08/17 16:32
 **/
public class CompletableFutureMallDemo {

    private static final List<NetMall> list = Arrays.asList(
            new NetMall("jd"),
            new NetMall("taoBao"),
            new NetMall("dangDang")
    );

    /**
     * step by step
     * 使用map映射做转换
     *
     */
    public static List<String> getPrice(List<NetMall> list, String productName) {
        //这个是一个一个调用并返回，效率慢
        return list
                .stream()
                .map(netMall ->
                        String.format(productName + "in %s is %.2f"
                                , netMall.getNetMallName()
                                , netMall.calcPrice(productName)))
                .toList();
    }

    /**
     * 使用CompletableFuture
     *
     * @param list 商城列表
     * @param productName 商品名字
     * @return 每个商城的该商品的价格
     */
    public static List<String> getPriceByCompletableFuture(List<NetMall> list, String productName) {
        //先将商城列表进行流转换，使用map转换为CompletableFuture.supplyAsync这个有返回值方法，返回值也是CompletableFuture
        //所以再次将CompletableFuture集合转换为每一项异步任务的结果，作为list返回
        return list.stream().map(netMall -> CompletableFuture.supplyAsync(() -> String.format(productName + "in %s is %.2f"
                , netMall.getNetMallName()
                , netMall.calcPrice(productName)))).toList().stream().map(CompletableFuture::join).toList();
    }

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        List<String> mysql = getPriceByCompletableFuture(list, "mysql");
        mysql.forEach(System.out::println);
        long endTime = System.currentTimeMillis();
        System.out.println("----------costTime：" + (endTime - startTime) + "毫秒");
    }
}

/**
 * 商城类
 */
class NetMall {
    /**
     * 商城名字，提供get方法
     */
    @Getter
    private final String netMallName;

    /**
     * 构造器初始化参数
     */
    public NetMall(String netMallName) {
        this.netMallName = netMallName;
    }

    /**
     * 停顿一秒后调用随机数并*2 + 传入的商品名字的第一位对应的字符码
     * @param productName 商品名
     * @return 价格
     */
    @SneakyThrows
    public double calcPrice(String productName) {
        TimeUnit.SECONDS.sleep(1);
        return ThreadLocalRandom.current().nextDouble() * 2 + productName.charAt(0);
    }
}
